home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Special 26
/
AMIGAplus Sonderheft 26 (2000)(Falke)(DE)(Track 1 of 2)[!].iso
/
Tools
/
GFX-Viewer
/
Animviewer
/
mpegvideo_datatype
/
mpegparseblock.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-03-29
|
10KB
|
460 lines
/*
**
** $VER: mpegparseblock.c 1.8 (27.5.97)
** mpegvideo.datatype 1.8
**
** block parsing
**
** Written 1996/1997 by Roland 'Gizzy' Mainz
**
*/
/*
#define NO_SANITY_CHECKS 1
*/
/* ansi includes */
#include <stdlib.h>
#include <string.h>
/* project includes */
#include "mpegmyassert.h"
#include "mpegvideo.h"
#include "mpegproto.h"
#include "mpegdecoders.h"
/* External declarations. */
extern const UBYTE zigzag_direct[ 64 ];
/*
*--------------------------------------------------------------
*
* ParseReconBlock --
*
* Parse values for block structure from bitstream.
* n is an indication of the position of the block within
* the macroblock (i.e. 0-5) and indicates the type of
* block (i.e. luminance or chrominance). Reconstructs
* coefficients from values parsed and puts in
* block.dct_recon array in vid stream structure.
* sparseFlag is set when the block contains only one
* coeffictient and is used by the IDCT.
*
* Results:
*
*
* Side effects:
* Bit stream irreversibly parsed.
*
*--------------------------------------------------------------
*/
#define DECODE_DCT_COEFF_FIRST DecodeDCTCoeffFirst
#define DECODE_DCT_COEFF_NEXT DecodeDCTCoeffNext
void ParseReconBlock( struct MPEGVideoInstData *mvid, int n )
{
Block *blockPtr = (&(curVidStream -> block));
int coeffCount = 0;
if( bufLength < (100 * SSP) )
{
correct_underflow( mvid );
}
{
int diff;
int size,
level,
i,
run,
pos,
coeff;
short int *reconptr;
UBYTE *iqmatrixptr,
*niqmatrixptr;
int qscale;
reconptr = (blockPtr -> dct_recon)[ 0 ];
/* Clear dct coeff matrix. */
memset( (void *)(blockPtr -> dct_recon), 0, sizeof( (blockPtr -> dct_recon) ) );
if( curVidStream -> mblock . mb_intra )
{
if( n < 4 )
{
/*
* Get the luminance bits. This code has been hand optimized to
* get by the normal bit parsing routines. We get some speedup
* by grabbing the next 16 bits and parsing things locally.
* Thus, calls are translated as:
*
* show_bitsX <--> next16bits >> (16-X)
* get_bitsX <--> val = next16bits >> (16-flushed-X);
* flushed += X;
* next16bits &= bitMask[flushed];
* flush_bitsX <--> flushed += X;
* next16bits &= bitMask[flushed];
*
* I've streamlined the code a lot, so that we don't have to mask
* out the low order bits and a few of the extra adds are removed.
* bsmith
*/
unsigned int next16bits,
index,
flushed;
show_bits16( next16bits );
index = next16bits >> (16 - 7);
size = dct_dc_size_luminance[ index ] . value;
flushed = dct_dc_size_luminance[ index ] . num_bits;
next16bits &= bitMask[ 16 + flushed ];
if( size != 0 )
{
flushed += size;
diff = next16bits >> (16 - flushed);
if( !(diff & bitTest[ 32 - size ]) )
{
diff = rBitMask[ size ] | (diff + 1);
}
}
else
{
diff = 0;
}
flush_bits( flushed );
if( n == 0 )
{
coeff = diff << 3;
if( ((curVidStream -> mblock . mb_address) - (curVidStream -> mblock . past_intra_addr)) > 1 )
{
coeff += 1024;
}
else
{
coeff += (blockPtr -> dct_dc_y_past);
}
(blockPtr -> dct_dc_y_past) = coeff;
}
else
{
coeff = (blockPtr -> dct_dc_y_past) + (diff << 3);
(blockPtr -> dct_dc_y_past) = coeff;
}
}
else
{
/*
* Get the chrominance bits. This code has been hand optimized to
* as described above
*/
unsigned int next16bits,
index,
flushed;
show_bits16( next16bits );
index = next16bits >> (16 - 8);
size = dct_dc_size_chrominance[ index ] . value;
flushed = dct_dc_size_chrominance[ index ] . num_bits;
next16bits &= bitMask[ 16 + flushed ];
if( size != 0 )
{
flushed += size;
diff = next16bits >> (16 - flushed);
if (!(diff & bitTest[ 32 - size ]))
{
diff = rBitMask[ size ] | (diff + 1);
}
}
else
{
diff = 0;
}
flush_bits( flushed );
if( n == 4 )
{
coeff = diff << 3;
if( curVidStream -> mblock . mb_address - curVidStream -> mblock . past_intra_addr > 1 )
{
coeff += 1024;
}
else
{
coeff += (blockPtr -> dct_dc_cr_past);
}
(blockPtr -> dct_dc_cr_past) = coeff;
}
else
{
coeff = diff << 3;
if( curVidStream -> mblock . mb_address - curVidStream -> mblock . past_intra_addr > 1 )
{
coeff += 1024;
}
else
{
coeff += (blockPtr -> dct_dc_cb_past);
}
(blockPtr -> dct_dc_cb_past) = coeff;
}
}
*reconptr = coeff;
i = 0;
pos = 0;
coeffCount = (coeff != 0);
if( (curVidStream -> picture . code_type) != D_TYPE )
{
qscale = curVidStream -> slice . quant_scale;
iqmatrixptr = curVidStream -> intra_quant_matrix[ 0 ];
while( 1 )
{
DECODE_DCT_COEFF_NEXT( run, level );
if( run == END_OF_BLOCK )
break;
assert( run != ESCAPE );
assert( run != END_OF_BLOCK );
i = i + run + 1;
assert( (i < 64) && (i >= 0) );
i = ABS( i ) % 64;
pos = zigzag_direct[ i ];
coeff = (level * qscale * ((int)iqmatrixptr[ pos ])) >> 3;
if( level < 0 )
{
coeff += (coeff & 1);
}
else
{
coeff -= (coeff & 1);
}
reconptr[ pos ] = coeff;
if( coeff )
{
coeffCount++;
}
}
flush_bits( 2 );
goto end;
}
}
else
{
niqmatrixptr = curVidStream -> non_intra_quant_matrix[ 0 ];
qscale = curVidStream -> slice . quant_scale;
DECODE_DCT_COEFF_FIRST( run, level );
/*
assert( run != ESCAPE );
assert( run != END_OF_BLOCK );
*/
i = run;
assert( (i < 64) && (i >= 0) );
i = ABS( i ) % 64;
pos = zigzag_direct[ i ];
if( level < 0 )
{
coeff = (((level << 1) - 1) * qscale * ((int)(niqmatrixptr[ pos ]))) >> 4;
coeff += (coeff & 1);
}
else
{
coeff = (((level << 1) + 1) * qscale * ((int)(*(niqmatrixptr + pos)))) >> 4;
coeff -= (coeff & 1);
}
reconptr[ pos ] = coeff;
if( coeff )
{
coeffCount = 1;
}
if( curVidStream -> picture . code_type != D_TYPE )
{
while( 1 )
{
DECODE_DCT_COEFF_NEXT( run, level );
if( run == END_OF_BLOCK )
break;
#ifdef COMMENTED_OUT
assert( run != ESCAPE );
#endif /* COMMENTED_OUT */
i = i + run + 1;
assert( (i < 64) && (i >= 0) );
i = ABS( i ) % 64;
pos = zigzag_direct[ i ];
if( level < 0 )
{
coeff = (((level << 1) - 1) * qscale * ((int)(niqmatrixptr[ pos ]))) >> 4;
coeff += (coeff & 1);
}
else
{
coeff = (((level << 1) + 1) * qscale * ((int)(*(niqmatrixptr + pos)))) >> 4;
coeff -= (coeff & 1);
}
reconptr[ pos ] = coeff;
if( coeff )
{
coeffCount++;
}
}
flush_bits( 2 );
goto end;
}
}
end:
if( coeffCount == 1 )
{
j_rev_dct_sparse( mvid, reconptr, pos );
}
else
{
#ifdef FLOATDCT
if( mvid -> mvid_Quality )
{
float_idct( reconptr );
}
else
#endif
{
j_rev_dct( reconptr );
}
}
}
}
/*
*--------------------------------------------------------------
*
* ParseAwayBlock --
*
* Parses off block values, throwing them away.
* Used with grayscale dithering.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void ParseAwayBlock( struct MPEGVideoInstData *mvid, int n )
{
unsigned int diff;
unsigned int size,
run;
int level;
if( bufLength < (100 * SSP) )
{
correct_underflow(mvid);
}
if( curVidStream -> mblock . mb_intra )
{
/* If the block is a luminance block... */
if( n < 4 )
{
/* Parse and decode size of first coefficient. */
DecodeDCTDCSizeLum( size );
/* Parse first coefficient. */
if( size != 0 )
{
get_bitsn( size, diff );
}
}
else /* Otherwise, block is chrominance block... */
{
/* Parse and decode size of first coefficient. */
DecodeDCTDCSizeChrom( size );
/* Parse first coefficient. */
if( size != 0 )
{
get_bitsn( size, diff );
}
}
}
else /* Otherwise, block is not intracoded... */
{
/* Decode and set first coefficient. */
DECODE_DCT_COEFF_FIRST( run, level );
assert( run != ESCAPE );
assert( run != END_OF_BLOCK );
}
/* If picture is not D type (i.e. I, P, or B)... */
if( curVidStream -> picture . code_type != D_TYPE )
{
/* While end of macroblock has not been reached... */
while( 1 )
{
/* Get the dct_coeff_next */
DECODE_DCT_COEFF_NEXT( run, level );
if( run == END_OF_BLOCK )
break;
assert( run != ESCAPE );
assert( run != END_OF_BLOCK );
}
/* End_of_block */
flush_bits( 2 );
}
}